import time

import math

from common.third_party.devmem import DevMem, DevMemCache
from services.ad936x.api import Ad936xApi, DoubleGain, DoubleFrequency
from settings import settings
from ctypes import c_int32

values = []
class DebugTCL:
    __slots__ = ['base_address', 'fd']

    def __init__(self):
        # Начальный адрес карты памяти IP (см. Vivado Address Editor) / hex
        self.base_address = 0x83E0_0000
        # Частота ядра (Гц)
        self.fd = 60_000_000

    @staticmethod
    def read(address: int, signed=False) -> int:
        if not settings.DEBUG:
            mem = DevMem(address=address)
            return mem.get_value(signed)

    @staticmethod
    def write(address: int, value: int):
        if not settings.DEBUG:
            mem = DevMem(address=address)
            mem.write(value=value)

    @staticmethod
    def bitselect(word, number_bit):
        mask = 2 ** number_bit
        result = word & mask
        return result > 0

    def fieldselect(self, word, start, end):
        start, end = min(start, end), max(start, end)
        l = end - start + 1
        mask = (1 << l) - 1
        return (word >> start) & mask

    def check_ip(self) -> bool:
        rdata = self.read(self.base_address)
        if rdata != 0xBB40E64D:
            print(f"ERROR. IP-pilot not found at address ${self.base_address}")
        return rdata == 0xBB40E64D

    def status_l(self):
        rdata = self.read(self.base_address + 4 * 11, True)
        link = self.fieldselect(rdata, 10, 10)

        rdata = self.read(self.base_address + 4 * 10, True)
        amp_b = self.fieldselect(rdata, 0, 23)
        print(link == 1, math.log10(amp_b) * 10)

    def status(self):
        if self.check_ip():
            for i in range(1, 16):
                rdata = self.read(self.base_address + 4 * i, True)
                match i:
                    case 1:
                        version = f"{self.fieldselect(rdata, 31, 16)}.{self.fieldselect(rdata, 15, 0)}"
                    case 2:
                        enable = self.bitselect(rdata, 2)
                    case 3:
                        freq_tx = (rdata * self.fd) / 4294967296
                    case 4:
                        width = (self.fieldselect(rdata, 15, 0) + 2) * 1000000.0 / self.fd
                    case 5:
                        scale_factor_filter_sum = self.fieldselect(rdata, 7, 4)
                        scale_factor_mod_sum = self.fieldselect(rdata, 12, 8)
                        count_cycles = self.fieldselect(rdata, 16, 13)
                        threshold = self.fieldselect(rdata, 20, 17)
                    case 6:
                        cur_thershold = self.fieldselect(rdata, 23, 0)
                    case 7:
                        pick_a = self.fieldselect(rdata, 23, 0)
                    case 8:
                        pick_b = self.fieldselect(rdata, 23, 0)
                    case 9:
                        amp_a = self.fieldselect(rdata, 23, 0)
                    case 10:
                        amp_b = self.fieldselect(rdata, 23, 0)
                    case 11:
                        num_a = self.fieldselect(rdata, 3, 0)
                        num_b = self.fieldselect(rdata, 7, 4)
                        link_a = self.fieldselect(rdata, 8, 8)
                        link_b = self.fieldselect(rdata, 9, 9)
                        link = self.fieldselect(rdata, 10, 10)
                    case 12:
                        freq = (rdata * self.fd) / 4294967296

            print("------------------------------------------------------------")
            print(" Status IP-PILOT")
            print(f" Version:              {version}")
            print(f" Freq Rx:              {freq} Hz")
            print(f" Freq Tx:              {freq_tx} Hz")
            print(f" Width:                {width} us")
            print("-----------------------------------------------------------")
            print(f" Scale factor filter:  {scale_factor_filter_sum} ")
            print(f" Scale factor mod sum: {scale_factor_mod_sum} ")
            print(f" Count of cycles:      {count_cycles}")
            print(f" K threshold:          {threshold}")
            print("-----------------------------------------------------------")
            print(f" Enable:               {enable}")
            print(f" Current thershold:    {cur_thershold}")
            if link == 1:
                print(" STATUS:               LINK \n")
            else:
                print(" STATUS:               LOSS")
            if link_a == 1:
                print(f" Amplitude pick (A):   {pick_a}")
                print(f" Amplitude (A):        {amp_a}")
                print(f" Num element (A):      {num_a}")

            if link_b == 1:
                print(f" Amplitude pick (B):   {pick_b}")
                print(f" Amplitude (B):        {amp_b}")

                print(f" Amplitude (B):        {math.log10(amp_b) * 10} db")
                print(f" Num element (B):      {num_b}")
                values.append(math.log10(amp_b) * 10)
                deltas = values[-8:]
                print(f' Max delta of 8:       {max(deltas) - min(deltas)}')




    def sys_reset(self):
        i = 2
        address = self.base_address + 4 * i
        self.write(address, 1)

    def set_k_filter(self, value):
        i = 5
        address = self.base_address + 4 * i
        rdata = self.read(address)
        rdata = rdata & 4294967055
        data = rdata + value * 16
        self.write(address, data)

    def set_k_sum(self, value):
        i = 5
        address = self.base_address + 4 * i
        rdata = self.read(address)
        rdata = rdata & 4294959359
        data = rdata + value * 256
        self.write(address, data)

    def set_cycles(self, value):
        i = 5
        address = self.base_address + 4 * i
        rdata = self.read(address)
        rdata = rdata & 4294844415
        data = rdata + value * 8192
        self.write(address, data)

    def set_thresh(self, value):
        i = 5
        address = self.base_address + 4 * i
        rdata = self.read(address)
        rdata = rdata & 4293001215
        data = rdata + value * 131072
        self.write(address, data)

    def set_freq_rx(self, freq=999450.6835937):
        freq_code = int((4294967296 * freq) / self.fd)
        address = self.base_address + 4 * 12
        self.write(address, freq_code)

    def set_freq_tx(self, freq=999450.6835937):
        freq_code = int((4294967296 * freq) / self.fd)
        address = self.base_address + 4 * 3
        self.write(address, freq_code)

    def set_enabled(self, enable: bool):
        address = self.base_address + 4 * 2
        self.write(address, 4 * enable)

    def reset(self):
        address = self.base_address + 4 * 2
        DevMem(address=address)[0] = True
        DevMem(address=address)[0] = False


    def set_width(self, width: int):
        width_code = int((width * self.fd) / 1000000 - 2)

        address = self.base_address + 4 * 4
        self.write(address, width_code)


def sync_ad3(index: int):
    SERVICE_CLOCK = 0x43C5_0000
    AD_API = Ad936xApi()
    mem = DevMemCache()

    ad_index = [0, 0, 1, 1, 2, 2][index]
    gain = [20, 20, 15, 15, 15, 15][index]
    config = AD_API.get_config(ad_index)
    AD_API.set_gain(3, DoubleGain(gain_0=gain, gain_1=gain))
    AD_API.set_center_frequency(3, DoubleFrequency(
        rx_frequency=config.tx_frequency,
        tx_frequency=config.tx_frequency
    ))

    multiplexer_state = [4, 5, 3, 2, 1, 0][index]
    mem.get(SERVICE_CLOCK, 1)\
        .write(0, multiplexer_state)




ctl = DebugTCL()
ctl.set_thresh(3)
ctl.set_cycles(15)
while True:
    ctl.status()
    time.sleep(1.4)


import time
from settings import settings
#
# def _read_power_dma(index: int):
#     correct_number = [40, 40, 32, 32, 32, 32][index]
#     index2 = [4, 5, 0, 1, 2, 3][index]
#     with open(f'{settings.ROOT_PATH}/environment/dma/power_meters', 'r') as file:
#         data = file.read().split('\n')
#         line = data[index]
#         line1 = data[index2]
#         io = line.split(' ')
#         io1 = line1.split(' ')
#         return float(io1[0]), float(io[1]) - correct_number
#
# def read_pilot_state_dma_e5(index: int, averaging: bool = False):
#     with open(f'{settings.ROOT_PATH}/environment/dma/pilot_states', 'r') as file:
#         line = file.read().split('\n')[index]
#         ps = line.split(' ')
#
#         return float(ps[0]), ps[1] == 'true'
#
# def print_power():
#     power, link_status = read_pilot_state_dma_e5(0)
#     print(f'{power:.3f}, {link_status}')
#
#
# while True:
#     print_power()
#     time.sleep(10.0)
import os

# from common.third_party.devmem import DevMem
#
#
# def _write_offset(addr: int, offset: float) -> None:
#     delta_theta = round((max(min(offset, 100), -100) * 1_000_000) * (2 ** 30) / 60_000_000)
#
#     DevMem(address=addr)\
#         .write(0, delta_theta)
#
#
# _write_offset(0x83E6_0000, -7.5)
# _write_offset(0x83E6_0004, -7.5)

# from settings import settings
# import time
#
# def _read_power_dma(index: int):
#     correct_number = [40, 40, 32, 32, 32, 32][index]
#     index2 = [4, 5, 0, 1, 2, 3][index]
#     with open(f'{settings.ROOT_PATH}/environment/dma/power_meters', 'r') as file:
#         data = file.read().split('\n')
#         line = data[index]
#         line1 = data[index2]
#         io = line.split(' ')
#         io1 = line1.split(' ')
#         return float(io1[0]), float(io[1]) - correct_number
#
#
# prev = _read_power_dma(2)
# count = 0
# while True:
#     time.sleep(0.1)
#     cur = _read_power_dma(2)
#     count += 1
#
#     if prev != cur:
#         print(count, prev, cur)
#         prev = cur
#         count = 0
#

import os
# import subprocess
#
# def _check_modem():
#     log = subprocess.run(['systemctl', 'status', 'wtelitncm'], stdout=subprocess.PIPE)
#     status = log.stdout.split(b'\n')[-2].split(b' ')
#     return status[-1] == b'OK' and status[-2] == b'Connect'
#
#
# print(_check_modem())



# import asyncio

# from services.server_integration.api import ServerIntegrationApi
#
# async def main():
#     ServerIntegrationApi().raise_alarm('STR1InputPower', value=3.0)
#
#
# if __name__ == '__main__':
#     asyncio.new_event_loop()\
#         .run_until_complete(main())


from auth.utilities import get_password_hash


# print(get_password_hash('irz@radius'))
# print(get_password_hash('irz..475'))






